// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#pragma once

#include <atomic>
#include <climits>
#include <cstdint>
#include <iosfwd>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <variant>
#include <vector>
#include <turbo/meta/compare.h>
#include <turbo/strings/string_builder.h>
#include <turbo/base/checked_cast.h>
#include <nebula/util/endian.h>
#include <turbo/base/macros.h>
#include <turbo/utility/status.h>
#include <nebula/types/type_fwd.h>
#include <nebula/types/data_type.h>
#include <nebula/types/type_holder.h>
#include <nebula/types/fundamental.h>
#include <nebula/types/meta/null_type.h>
#include <nebula/types/field.h>
#include <nebula/types/meta/int_types.h>
#include <nebula/types/meta/boolean_type.h>
#include <nebula/types/meta/decimal_type.h>
#include <nebula/types/meta/float_types.h>
#include <nebula/types/meta/list_type.h>
#include <nebula/types/meta/map_type.h>
#include <nebula/types/meta/dictionary_type.h>
#include <nebula/types/meta/date_type.h>
#include <nebula/types/schema.h>
#include <nebula/types/meta/struct_type.h>
#include <nebula/types/union_type.h>
#include <nebula/types/meta/string_type.h>


namespace nebula {
    constexpr int64_t kBinaryMemoryLimit = std::numeric_limits<int32_t>::max() - 1;


    // ----------------------------------------------------------------------
    // Schema

    enum class Endianness {
        Little = 0,
        Big = 1,
#if NEBULA_LITTLE_ENDIAN
        Native = Little
#else
        Native= Big
#endif
    };

    TURBO_EXPORT
    std::string endianness_to_string(Endianness endianness);

    // ----------------------------------------------------------------------

    namespace internal {
        constexpr bool may_have_validity_bitmap(Type::type id) {
            switch (id) {
                case Type::NA:
                case Type::DENSE_UNION:
                case Type::SPARSE_UNION:
                case Type::RUN_END_ENCODED:
                    return false;
                default:
                    return true;
            }
        }

        TURBO_DEPRECATED("Deprecated in 17.0.0. Use may_have_validity_bitmap() instead.")

        constexpr bool has_validity_bitmap(Type::type id) { return may_have_validity_bitmap(id); }

        TURBO_EXPORT
        std::string to_string(Type::type id);

        TURBO_EXPORT
        std::string to_type_name(Type::type id);

        TURBO_EXPORT
        std::string to_string(TimeUnit::type unit);
    } // namespace internal

    // Helpers to get instances of data types based on general categories

    /// \brief Signed integer types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &signed_int_types();

    /// \brief Unsigned integer types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &unsigned_int_types();

    /// \brief Signed and unsigned integer types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &int_types();

    /// \brief Floating point types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &floating_point_types();

    /// \brief Number types without boolean - integer and floating point types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &numeric_types();

    /// \brief Binary and string-like types (except fixed-size binary)
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &base_binary_types();

    /// \brief Binary and large-binary types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &binary_types();

    /// \brief String and large-string types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &string_types();

    /// \brief Temporal types including date, time and timestamps for each unit
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &temporal_types();

    /// \brief Interval types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &interval_types();

    /// \brief Duration types for each unit
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &duration_types();

    /// \brief Numeric, base binary, date, boolean and null types
    TURBO_EXPORT
    const std::vector<std::shared_ptr<DataType> > &primitive_types();
} // namespace nebula
